/**
 * \file  plugin_admin.h
 * \brief Implementation of BasePlugin and BasePluginNode classes.
 *
 * ASO: Antiviral Sequence Optimizer
 * <http://aso.googlecode.com/>
 * Copyright (C) 2010 Velez Ezequiel, Peralta Andres, FuDePAN
 *
 * This file is part of the ASO project.
 *
 * Contents:       Header file for ASO providing class BasePlugin and class BasePluginNode.
 *
 * System:         ASO
 * Language:       C++
 *
 * Author:         Velez Ezequiel, Peralta Andres
 * E-Mail:
 *
 * ASO is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * ASO is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with ASO.  If not, see <http://www.gnu.org/licenses/>.
 *
 */

#include "libpluginaso/libpluginaso.h"

struct BasePluginNode: public TherapyNode
{
    /*! Constructor */
    BasePluginNode(const biopp::PseudoNucSequence& sequence, TherapyNode* parent, const AntiviralSet& av, DistanceValue value, const size_t id, CombinatoryPolicy* comb)
        : TherapyNode(sequence, parent, av, value, id, comb)
    {}

    /*! Destructor */
    ~BasePluginNode()
    {}

    /*! Metodo encargado de clonar un nodo */
    inline BasePluginNode* clone() const;
    /*! Metodo que asigna puntaje a las terapias */
    inline Score scoring() const;
    /*! Metodo que determina que hacer con una terapia (continuarla, descartarla) */
    inline TherapyStatus continue_therapy() const;
    /*! Permite cambiar el combinador de AV en caso de fallo virologico */
    inline CombinatoryPolicy* virologic_failure(const CombinationStatus& status);
};

inline BasePluginNode* BasePluginNode::clone() const
{
    return new BasePluginNode(sequence, parent, antivirals, value, id, combPolicy);
}

inline Score BasePluginNode::scoring() const
{
    return 0;
}

inline TherapyStatus BasePluginNode::continue_therapy() const
{
    return Continue;
}

inline CombinatoryPolicy* BasePluginNode::virologic_failure(const CombinationStatus&)
{
    return NULL;
}

class BasePlugin: public Plugin
{
public:
    /*! Costructor*/
    BasePlugin(Unplugged::LibraryHandler handle)
        : Plugin(handle),
          NAME("base plugin"),
          MIN_SCORE_VALUE(0.0f),
          availableAntivirals()
    {}
    /*! Función que genera un nodo */
    inline TherapyNode* create_node(const biopp::PseudoNucSequence& sequence, TherapyNode* parent, const AntiviralSet& av, DistanceValue value, const size_t id) const;
    /*! Función que retorna el valor minimo que puede tener una terapia */
    inline Score get_min_scoring_value() const;
    /*! Retorna la politica para generar el árbol */
    inline GenerationPolicy* get_generation_policy() const;
    /*! Retorna la lista de parametros a inicializar */
    inline void get_params(ParameterList& params);
    /*! Retorna true si se valida la BD */
    inline bool accepts_db(AVIterator avIt, AntiviralsNames& rejectedAntivirals);
    /*! Retorna el nombre del plugin */
    inline const string& get_name() const;
    /*! valida una combinación de antivirales */
    inline bool validate_combination(const AntiviralSet& antivirals) const;
    /*! Define la matriz de distancias. */
    inline void get_distance_matrix(biopp::DistanceMatrix& matrix) const;
    /*! Destructor */
    ~BasePlugin()
    {}
private:
    const string NAME;
    const Score  MIN_SCORE_VALUE;
    biopp::DistanceMatrix DISTMATRIX;
    Avs availableAntivirals;
};

/*! Creo el nodo de acuerdo a mis necesidades */
inline TherapyNode* BasePlugin::create_node(const biopp::PseudoNucSequence& sequence, TherapyNode* parent, const AntiviralSet& av, DistanceValue value, const size_t id) const
{
    EmptyCombinatory* e = new EmptyCombinatory("empty");
    return new BasePluginNode(sequence, parent, av, value, id, e);
}

inline Score BasePlugin::get_min_scoring_value() const
{
    return MIN_SCORE_VALUE;
}

inline GenerationPolicy* BasePlugin::get_generation_policy() const
{
    return new  Depth;
}

inline void BasePlugin::get_params(ParameterList&)
{}

/*! Pre: avIt esta posicionado en el primer elemento */
inline bool BasePlugin::accepts_db(AVIterator, AntiviralsNames&)
{
    return true;
}

inline const string& BasePlugin::get_name() const
{
    return NAME;
}

inline bool BasePlugin::validate_combination(const AntiviralSet&) const
{
    return true;
}

inline void BasePlugin::get_distance_matrix(biopp::DistanceMatrix&) const
{}


